from __future__ import absolute_import
from django import newforms as forms
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response
from .models import ListDoc, UserProfile
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.auth.models import User
from django.template import RequestContext
from django.conf import settings
import re

@login_required
def text_file(request, template_name='onli/text_list.html',
        mimetype='text/plain'):
    """A text file of the task list"""
    user_list_doc = ListDoc.objects.get_user_list(request)
    return render_to_response(template_name,
                            {'raw_content': user_list_doc.raw_content},
                            mimetype=mimetype)

@login_required
def list_all(request):
    """Lists all items, unless user's list is empty, then it sends user to the
    add/edit page"""
    try:
        user_list_doc = ListDoc.objects.get_user_list(request)
    except:
        return HttpResponseRedirect (reverse('add_edit'))
    check_hash, all_items = user_list_doc.get_enum_list()
    # included RequestContext so the template knows the user.
    return render_to_response('onli/item_list.html',
                            {'items': all_items,'list_type': 'All','check_hash': check_hash},
                            context_instance=RequestContext(request))

@login_required
def context(request, context=''):
    """Lists all items for a particular @context or if no context is passes a blank query
    contexts should be passed without the '@', which will be added to make the query more
    robust"""
    if context:
        context = '@'+context
    user_list_doc = ListDoc.objects.get_user_list(request)
    check_hash, context_items = user_list_doc.get_enum_list(context)
    return render_to_response('onli/item_list.html',
                            {'items': context_items,'list_type': context,'check_hash': check_hash},
                            context_instance=RequestContext(request))

@login_required
def project(request, project=''):
    """Lists all items for a particular p:project or if no project is passes a blank query.
    Projects should be passed without the 'p:', but it is added when making the query"""
    if project:
        project = 'p:'+project
    user_list_doc = ListDoc.objects.get_user_list(request)
    check_hash, project_items = user_list_doc.get_enum_list(project)
    return render_to_response('onli/item_list.html',
                            {'items': project_items,'list_type': project,'check_hash': check_hash},
                            context_instance=RequestContext(request))

@login_required
def add_edit(request):
    """Allows initial entry and editing of task list.  """
    try:
        user_list_doc = ListDoc.objects.get_user_list(request)
        ListDocForm = forms.models.form_for_instance(user_list_doc)
    except:
        ListDocForm = forms.models.form_for_model(ListDoc)
    # Uses widget to control the text entry area
    # ??? should this type of formatting be in the template not the view?
    ListDocForm.base_fields['raw_content'].widget=forms.Textarea(attrs={'rows': 30, 'cols': 50})
    if request.method == 'POST':
        form = ListDocForm(request.POST)
        if form.is_valid():
            list_doc = form.save(commit=False)
            # user is not editable, so it must be added.
            # ??? should we only update the user on creation, not on edit?
            list_doc.user = request.user
            list_doc.save()
            return HttpResponseRedirect( list_doc.get_absolute_url() )
    else:
        form = ListDocForm()
    return render_to_response('onli/add_edit.html',
                            {'form': form},
                            context_instance=RequestContext(request))

@login_required
def edit_user_details(request):
    """Enter and edit the user details."""
    try:
        user_profile = UserProfile.objects.get(user=request.user.id)
        UserDetailsForm = forms.models.form_for_instance(user_profile)      
    except:
        UserDetailsForm = forms.models.form_for_model(UserProfile)
    if request.method == 'POST':
        form = UserDetailsForm(request.POST)
        if form.is_valid():
            temp_form = form.save(commit=False)
            temp_form.user = request.user
            temp_form.save()
            return HttpResponseRedirect( reverse('list_all') )
    else:
        form = UserDetailsForm()
    return render_to_response('onli/edit_user_details.html',
                            {'form': form},
                            context_instance=RequestContext(request))

def mark_completed(request,item_num,check_hash):
    user_list_doc = ListDoc.objects.get_user_list(request)
    user_list_doc.mark_item(item_num,check_hash)
    if request.GET.has_key('next'):
        redirect = request.GET['next']
    else:
        redirect = user_list_doc.get_absolute_url()
    return HttpResponseRedirect ( redirect )

@user_passes_test(lambda u: u.is_authenticated() and u.is_staff)
def web_check_mail(request):
    """Allows a staff member to kick off mail using a web page.
    I have mostly used this for debugging my mail setup"""
    responses = check_mail()
    return render_to_response('onli/check_mail.html',
                            {'responses': responses},
                            context_instance=RequestContext(request))

def check_mail():
    """Checks an IMAP account specified in the settings.py file, grabs all messages in
    the inbox, and sends the address and the first word in the body of the email
    over to send_mail().  It returns a list of the responses that were sent.
    The functionality allows mobile users to text the system and get a response.
    see cron_email.py if you want to run this from a cron job to periodically check and
    send responses"""
    
    import imaplib, email
    
    # Values for response if mailbox is empty
    responses = [] #debug info
    
    # Login to the IMAP, values stored in Django settings file
    M = imaplib.IMAP4_SSL(host=settings.IMAP_HOST,port=settings.IMAP_PORT)
    M.login(settings.ONLI_IMAP_USER, settings.ONLI_IMAP_PASSWORD)
    M.select()
    
    # Check that there is something in the mailbox.
    if M.select()[1][0] != '0':
        
        # Get all of the 
        typ, data = M.search(None, 'ALL')
        for num in data[0].split():
            raw = M.fetch(num, '(RFC822)')
            msg = email.message_from_string(raw[1][0][1])
            body = msg.get_payload()
            query = body.split()[0]
            address_info = msg['From']
            addr_search = re.compile(r'[\w\-][\w\-\.]*@[\w\-][\w\-\.]+[a-zA-Z]{1,4}')
            address = addr_search.findall(address_info)
            if send_response(address,query) != False:
                responses.append(''.join(address)+':'+query) #debug info
                ok, error = M.store(num, 'FLAGS', '(\Deleted)')
            else:
                responses.append('no such user'+''.join(address)+':'+query) #debug info
                ok, error = M.store(num, 'FLAGS', '(\Flagged)')

    # You could call M.expunge() here, but it is expensive if you are checking frequently.
    M.close()
    M.logout()
    return responses

def send_response(address,query):
    """Given an email address and a query this sends the matching results to an email address,
    especially for a mobile text."""
    from django.core.mail import send_mail
    from django.template.loader import render_to_string

    str_address = ''.join(address)
    try:
        user_profile = UserProfile.objects.get(mobile_email=str_address)
    except:
        return False
    user = User.objects.get(id=user_profile.user.id)
    user_list_doc = ListDoc.objects.get(user=user.id)
    response_subject = 'Items: '+ query
    if query.lower() == 'all':
        query = ''
    check_hash, result_items = user_list_doc.get_enum_list(query,raw=True)
    message = render_to_string('onli/item_list_email.txt',
                            { 'items': result_items,
                            'query': query})
    send_mail(response_subject, message, settings.DEFAULT_FROM_EMAIL, address)